package snow_flake

import (
	"go-utils/snow_flake/snow_flake_interface"
	"strconv"
	"sync"
	"time"
)

var machineId int64 = 111

const (
	startTimeStamp = int64(1483228800000)              //开始时间截 (2017-01-01)
	machineIdBits  = uint(10)                          //机器id所占的位数
	sequenceBits   = uint(12)                          //序列所占的位数
	machineIdMax   = int64(-1 ^ (-1 << machineIdBits)) //支持的最大机器id数量
	sequenceMask   = int64(-1 ^ (-1 << sequenceBits))  //
	machineIdShift = sequenceBits                      //机器id左移位数
	timestampShift = sequenceBits + machineIdBits      //时间戳左移位数
)

// 创建一个雪花算法生成器(生成工厂)
func CreateSnowflake() snow_flake_interface.Interface {
	return &snowflake{
		timestamp: 0,
		machineId: machineId,
		sequence:  0,
	}
}

type snowflake struct {
	sync.Mutex
	timestamp int64
	machineId int64
	sequence  int64
}

// 生成分布式ID
func (s *snowflake) GetId() int64 {
	s.Lock()
	defer func() {
		s.Unlock()
	}()
	now := time.Now().UnixNano() / 1e6
	if s.timestamp == now {
		s.sequence = (s.sequence + 1) & sequenceMask
		if s.sequence == 0 {
			for now <= s.timestamp {
				now = time.Now().UnixNano() / 1e6
			}
		}
	} else {
		s.sequence = 0
	}
	s.timestamp = now
	r := (now-startTimeStamp)<<timestampShift | (s.machineId << machineIdShift) | (s.sequence)
	return r
}

func (s *snowflake) GetIdStr() string {
	return strconv.FormatInt(s.GetId(), 10)
}
